class TaskScheduler {
    constructor(tasks, options = {}) {
        this.tasks = tasks;
        this.batchSize = options.batchSize || 1000; // 每批执行任务数量
        this.mode = options.mode || 'worker'; // 'timeout' | 'idle' | 'raf' | 'worker'
        this.worker = null;
    }
    start() {
        if (this.mode === 'timeout') {
            this.runWithTimeout();
        } else if (this.mode === 'idle') {
            this.runWithIdle();
        } else if (this.mode === 'raf') {
            this.runWithRAF();
        } else if (this.mode === 'worker') {
            this.runWithWorker();
        }  else {
            throw new Error(`未知模式: ${this.mode}`);
        }
    }
    runWithTimeout() {
        let i = 0
        const step = () => {
            const end = Math.min(i + this.batchSize, this.tasks.length)
            for (; i < end; i ++) {
                this.tasks[i]()
            }
            if (i < this.tasks.length) {
                // 如果还有未执行的任务，通过 setTimeout 将下一个批处理放入事件队列，让浏览器有机会处理其他事件（如 UI 渲染、用户交互等），避免长时间阻塞主线程。
                setTimeout(step)
            }
        }
        step()
    }
    runWithIdle() {
        let i = 0
        const step = (deadline) => {
            // 当前帧（Frame）剩余多少毫秒可用来执行 JS 任务。
            // 当它返回 0 或接近 0 时，说明这帧的时间已经用完，需要等到下一帧再执行
            while (i< this.tasks.length && deadline.timeRemaining() > 0) {
                this.tasks[i++]()
            }
            if (i < this.tasks.length) {
                 requestIdleCallback(step)
            }
        }
        requestIdleCallback(step)
    }
    runWithRAF() {
        let i = 0;
        const step = () => {
        let start = performance.now();
        while (i < this.tasks.length && performance.now() - start < 16) {
            this.tasks[i++]();
        }
        if (i < this.tasks.length) {
            requestAnimationFrame(step);
        }
        };
        requestAnimationFrame(step);
    }
    runWithWorker() {
        console.log('俩咯')
        // 创建一个 Worker（用 Blob 动态创建，避免额外 .js 文件）
        const blob = new Blob([`
            self.onmessage = function(e) {
                const { tasks, batchSize } = e.data
                let results = []
                for (let i = 0; i < tasks.length; i ++) {
                    // 模拟执行任务（Worker不能直接执行函数，只能执行计算）
                    results.push(tasks[i] * 2);
                    if (results.length >= batchSize) {
                        self.postMessage({ batch: results })
                        results = []
                    }
                }
                if (results.length) {
                    self.postMessage({ batch: results });
                }
                self.postMessage({ done: true });
            }
        `], { type: 'application/javascript' })
        this.worker = new Worker(URL.createObjectURL(blob))
        
        // Worker 不能直接传函数数组，这里传数据
        const numericTasks = this.tasks.map((_, idx) => idx);
        this.worker.postMessage({ tasks: numericTasks, batchSize: this.batchSize });
        
        this.worker.onmessage = (e) => {
            const { batch, done } = e.data;
            if (batch) {
                console.log('收到 Worker 数据', batch.length);
            }
            if (done) {
                console.log('Worker 任务全部完成');
                this.worker.terminate();
            }
        }
    }
}

const tasks = Array.from({ length: 1_000_000 }, (_, idx) => () => {
  if (idx % 200000 === 0) console.log('执行到任务', idx);
});

// 你可以切换 mode: 'timeout' | 'idle' | 'raf'
new TaskScheduler(tasks, { batchSize: 5000 }).start();